/**
 * 友魄科技
 */
package utils;

import org.apache.commons.lang.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * 日期辅助类
 * 
 * @author zhangzichao@jingkao.net 2012年08月01日
 */
public class DateUtils {

    public final static long ONE_MIN = 60 * 1000l;

    public final static long ONE_HOUR = 60 * ONE_MIN;

    public final static long ONE_DAY = 24 * ONE_HOUR;

	public final static String ISO_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS";

	public final static String DEFAULT_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

	public final static String DEFAULT_HOUR_FORMAT = "yyyy-MM-dd-HH";

	public final static String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";

	public final static String SHORT_TIME_FORMAT = "yyyy-MM-dd HH:mm";

	public final static String FULL_SEQ_FORMAT = "yyyyMMddHHmmssSSS";

	public final static String[] MULTI_FORMAT = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM" ,"yyyy-MM-dd-HH"};

	public final static String FORMAT_YYYY = "yyyy";

	public final static String FORMAT_YYYYMM = "yyyyMM";

	public final static String FORMAT_YYYYMMDD = "yyyyMMdd";

	public final static String FORMAT_YYYYMMDDHH = "yyyyMMddHH";

	public static ThreadLocal<Calendar> calendarThreadLocal = new ThreadLocal<Calendar>();


	/**
	 * 周期类型枚举类
	 * 
	 * @creation 2014-8-4
	 * 
	 */
	public static enum PeriodTypeEnum {
		HOUR(0, "小时"), DAY(1, "天"), WEEK(2, "周"), MONTH(3, "月");

		private int periodType;
		private String desc;

		private PeriodTypeEnum(int periodType, String desc) {
			this.desc = desc;
			this.periodType = periodType;
		}

		public int getPeriodType() {
			return periodType;
		}

		public String getDesc() {
			return desc;
		}

		public static PeriodTypeEnum getPeriodTypeEnum(int periodType) {
			for (PeriodTypeEnum pt : values()) {
				if(pt.getPeriodType() == periodType){
					return pt;
				}
			}
			return null;
		}
	}

	public static String formatDate(Date date) {
		if (date == null) {
			return "";
		}
		return new SimpleDateFormat(DEFAULT_DATE_FORMAT).format(date);
	}

	public static String formatDate(Date date, String format) {
		if (date == null) {
			return null;
		}
		return new SimpleDateFormat(format).format(date);
	}

	public static Integer formatDateToInt(Date date, String format) {
		if (date == null) {
			return null;
		}
		return Integer.valueOf(new SimpleDateFormat(format).format(date));
	}

	public static Long formatDateToLong(Date date, String format) {
		if (date == null) {
			return null;
		}
		return Long.valueOf(new SimpleDateFormat(format).format(date));
	}

	public static String formatTime(Date date) {
		if (date == null) {
			return null;
		}
		return new SimpleDateFormat(DEFAULT_TIME_FORMAT).format(date);
	}

	public static String getDateHour(){
		SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_HOUR_FORMAT);
		return formatter.format(new Date());
	}

	public static String getWeek(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		cal.setTime(date);
		int year = cal.get(Calendar.YEAR);
		int weeks = cal.get(Calendar.WEEK_OF_YEAR);
		String week = weeks < 10?"0"+weeks:String.valueOf(weeks);
		return year + week;
	}
	public static Date addDays(Date date,Integer day){
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DAY_OF_YEAR,day);
		return cal.getTime();
	}

	public static String getLastWeek(Date date){
		Calendar cal = Calendar.getInstance();
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		cal.setTime(date);
		int year = cal.get(Calendar.YEAR);
		int weeks = cal.get(Calendar.WEEK_OF_YEAR);
		//如果本周是第一周
		if(weeks == 1){
			//获取上一年最后一周
			year = year - 1;
			date = parseMultiFormatDate(year + "-12-31");
			cal.setTime(date);
			weeks = cal.get(Calendar.WEEK_OF_YEAR);
		}else{
			weeks = weeks - 1;
		}
		String week = weeks < 10?"0"+weeks:String.valueOf(weeks);
		return year + week;
	}


	public static String formatDateNow() {
		return formatDate(DateUtils.currentDate());
	}

	/**
	 * 为了便于在模拟数据程序中控制业务数据获取到的当前时间
	 * 提供一个帮助类处理当前时间，为了避免误操作，只有在devMode开发模式才允许“篡改”当前时间
	 * @return
	 */
	public static Date currentDate() {
		return new Date();
	}

	public static Date parseMultiFormatDate(String date) {
		try {
			return org.apache.commons.lang.time.DateUtils.parseDate(date, MULTI_FORMAT);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}


	/**
	 * 返回某个周期的开始时间
	 * 
	 * @param date
	 * @param periodTypeEnum
	 * @return
	 */
	public static Date getStartDate(Date date, PeriodTypeEnum periodTypeEnum) {
		if (date == null || periodTypeEnum == null)
			throw new RuntimeException("Date and PreiodTypeEnum must be not null");
		Calendar calendar = getCalendar(date);
		if (periodTypeEnum == PeriodTypeEnum.WEEK) {
			calendar.setFirstDayOfWeek(Calendar.MONDAY);
			calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		}
		if (periodTypeEnum == PeriodTypeEnum.MONTH) {
			calendar.set(Calendar.DAY_OF_MONTH, 1);
		}
		if (periodTypeEnum != PeriodTypeEnum.HOUR) {
			calendar.set(Calendar.HOUR_OF_DAY, 0);
		}
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);

		return calendar.getTime();
	}

	/**
	 * 返回某个周期的结束时间
	 * 
	 * @param date
	 * @param periodTypeEnum
	 * @return
	 */
	public static Date getEndDate(Date date, PeriodTypeEnum periodTypeEnum) {
		if (date == null || periodTypeEnum == null){
			throw new RuntimeException("Date and preiodTypeEnum must be not null");
		}
		Calendar calendar = getCalendar(date);
		if (periodTypeEnum == PeriodTypeEnum.WEEK) {
			calendar.setFirstDayOfWeek(Calendar.MONDAY);
			calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
		}
		if (periodTypeEnum == PeriodTypeEnum.MONTH) {
			calendar.set(Calendar.DAY_OF_MONTH, 1);
			calendar.roll(Calendar.DAY_OF_MONTH, -1);
		}
		if (periodTypeEnum != PeriodTypeEnum.HOUR) {
			calendar.set(Calendar.HOUR_OF_DAY, 23);
		}
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		// calendar.set(Calendar.MILLISECOND, 999);

		return calendar.getTime();
	}

	// 返回日历
	public static Calendar getCalendar(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar;
	}

	/**
	 * 获得 days 后的日期
	 * 
	 * @param date
	 *            - 指定时间
	 * @param days
	 *            - 多少天后，可以是负数
	 * @return days 后的日期
	 */
	public static Date getNextDays(Date date, int days) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DAY_OF_MONTH, days);
		return cal.getTime();
	}

	/**
	 * 获得 days 后的日期，以当前时间为基准
	 * 
	 * @param days
	 *            - 多少天后
	 * @return days 后的日期
	 */
	public static Date getNextDays(int days) {
		return getNextDays(new Date(), days);
	}

	/**
	 * 获得 seconds 后的时间
	 * 
	 * @param date
	 *            - 指定时间
	 * @param seconds
	 *            - 多少秒后，可以是负数
	 * @return seconds 后的时间
	 */
	public static Date getNextSeconds(Date date, int seconds) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.SECOND, seconds);
		return cal.getTime();
	}

	/**
	 * 获得 minutes 后的时间
	 * 
	 * @param date
	 *            - 指定时间
	 * @param minutes
	 *            - 多少分钟后，可以是负数
	 * @return minutes 后的时间
	 */
	public static Date getNextMinutes(Date date, int minutes) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MINUTE, minutes);
		return cal.getTime();
	}

	/**
	 * 返回当前日期对应的 00:00:00 ~ 23:59:59 的时间
	 * 
	 * @return
	 */
	public static Date[] getTodayRange() {
		return getDateRange(new Date());
	}

	/**
	 * 返回指定日期的00:00:00 ~ 23:59:59 的时间
	 * 
	 * @param date
	 * @return
	 */
	public static Date[] getDateRange(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		Date beginTime = cal.getTime();

		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);

		Date endTime = cal.getTime();
		return new Date[] { beginTime, endTime };
	}

	/**
	 * 返回上个月的1号00:00:00 ~ 该月最后一天23:59:59 的时间
	 * 
	 * @return date数组:date[0]上月的第一天；date[1]上月的最后一天
	 */
	public static Date[] getLastMonthDate() {
		return getLastMonthDate(new Date());
	}

	/**
	 * 返回上个月的1号00:00:00 ~ 该月最后一天23:59:59 的时间
	 * 
	 * @param date
	 *            - 指定日期的上个月
	 * @return date数组:date[0]上月的第一天；date[1]上月的最后一天
	 * @author linyi 2015/2/13
	 */
	public static Date[] getLastMonthDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.DAY_OF_MONTH, 1);
		cal.add(Calendar.DAY_OF_MONTH, -1);
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 0);

		Date endTime = cal.getTime();

		cal.set(Calendar.DATE, 1);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);

		Date beginTime = cal.getTime();
		return new Date[] { beginTime, endTime };
	}

	/**
	 * 根据时间 获取该事件的小时开始时间 和小时的结束时间
	 * @param date
	 * @return
	 */
	public static Date[] getHourDate(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 0);

		Date endTime = cal.getTime();

		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);

		Date beginTime = cal.getTime();
		return new Date[] { beginTime, endTime };
	}

	/**
	 * 根据时间获取分钟之间的时间
	 * @param date
	 * @return
	 */
	public static Date[] getMinuteDate(Date date,int minutes) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);

		Date beginTime = cal.getTime();

		cal.add(Calendar.MINUTE,minutes);
		cal.set(Calendar.SECOND, 59);

		Date endTime = cal.getTime();
		return new Date[] { beginTime, endTime };
	}

	/**
	 * 返回指定日期的HH:00:00 时间
	 *
	 * @param date
	 *            需要修改的时间
	 * @return
	 */
	public static Date toHourStart(Date date) {
		return getHourDate(date)[0];
	}

	/**
	 * 返回指定日期的HH:59:59 时间
	 *
	 * @param date
	 *            需要修改的时间
	 * @return
	 */
	public static Date toHourEnd(Date date) {
		return getHourDate(date)[1];
	}



	/**
	 * 返回指定日期的00:00:00 时间
	 * 
	 * @param date
	 *            需要修改的时间
	 * @return
	 */
	public static Date toDayStart(Date date) {
		return getDateRange(date)[0];
	}

	/**
	 * 返回指定日期的23:59:59时间
	 * 
	 * @param date
	 *            需要修改的时间
	 * @return
	 */
	public static Date toDayEnd(Date date) {
		return getDateRange(date)[1];
	}

	/**
	 * 获得 seconds 后的时间，以当前时间为基准
	 * 
	 * @param seconds
	 * @return
	 */
	public static Date getNextSeconds(int seconds) {
		return getNextSeconds(new Date(), seconds);
	}

	/**
	 * string类型转换为long类型
	 * 
	 * @param strTime
	 *            要转换的string类型的时间，
	 * @param formatType
	 *            要转换的格式yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日 DateTimeFormat 里有定义
	 * @param idToSecond
	 *            true:转换成秒 false:返回毫秒
	 * @return
	 * @throws ParseException
	 * @throws ParseException
	 */
	public static long stringToLong(String strTime, String formatType, boolean idToSecond)
			throws ParseException {
		Date date = stringToDate(strTime, formatType);
		if (date == null) {
			return 0;
		} else {
			long currentTime = date.getTime();
			return idToSecond ? currentTime / 1000 : currentTime;
		}
	}

	/**
	 * string类型转换为date类型
	 *
	 * @param strTime
	 *            要转换的string类型的时间，
	 * @param formatType
	 *            要转换的格式yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日 DateTimeFormat 里有定义
	 * @return
	 * @throws ParseException
	 */
	public static Date stringToDate(String strTime, String formatType) throws ParseException {
		SimpleDateFormat formatter = new SimpleDateFormat(formatType);
		Date date = null;
		date = formatter.parse(strTime);
		return date;
	}

	/**
	 *
	 * @param date
	 *            要转换的date类型的时间，
	 * @param formatType
	 *            要转换的格式yyyy-MM-dd HH:mm:ss//yyyy年MM月dd日 DateTimeFormat 里有定义
	 * @return
	 * @throws ParseException
	 */
	public static String dateToString(Date date, String formatType) {
		if (date == null) {
			return "";
		}
		SimpleDateFormat formatter = new SimpleDateFormat(formatType);
		String str = null;
		str = formatter.format(date);
		return str;
	}

	/**
	 * 根据date获得年份
	 * 
	 * @param date
	 *            输入null的话，获得当前年份
	 * @return
	 */
	public static int getYearByDate(Date date) {
		Calendar cal = Calendar.getInstance();
		if (date != null) {
			cal.setTime(date);
		}
		int year = cal.get(Calendar.YEAR);
		return year;
	}

	/**
	 * 根据date获得月份
	 * 
	 * @param date
	 *            输入null的话，获得当前月份
	 * @return
	 */
	public static int getMonthByDate(Date date) {
		Calendar cal = Calendar.getInstance();
		if (date != null) {
			cal.setTime(date);
		}
		int month = cal.get(Calendar.MONTH) + 1;
		return month;
	}

	/**
	 * 返回从当月1号到date日期的天数 例如输入2014-04-18 则返回18
	 * 
	 * @param date
	 *            输入null的话，取当前日期
	 * @return
	 */
	public static int getDayByDate(Date date) {
		Calendar cal = Calendar.getInstance();
		if (date != null) {
			cal.setTime(date);
		}
		int day = cal.get(Calendar.DATE);
		return day;
	}

	/**
	 * 返回当月的第一天
	 * 
	 * @param date
	 *            - 指定的日期，如果不指定，默认为当前日期
	 * @return 当月的第一天
	 * @author linyi 2015/2/10
	 */
	public static Date getFirstDayOfMonth(Date date) {
		Calendar cal = Calendar.getInstance();
		if (date != null) {
			cal.setTime(date);
		}
		cal.set(Calendar.DAY_OF_MONTH, 1);
		return cal.getTime();
	}

	/**
	 * 2天之间相差多少天，精确到日期，时、分、秒默认都设为0 例如： 2014-11-06 23:59:59 与 2014-11-07 00:00:00
	 * dayDiff的结果为 1
	 * 
	 * @param start
	 * @param end
	 * @return
	 */
	public static int dayDiff(Date start, Date end) {
		Calendar startCalendar = getCalendar(start);
		Calendar endCalendar = getCalendar(end);
		startCalendar.set(Calendar.HOUR_OF_DAY, 0);
		startCalendar.set(Calendar.MINUTE, 0);
		startCalendar.set(Calendar.SECOND, 0);
		startCalendar.set(Calendar.MILLISECOND, 0);
		endCalendar.set(Calendar.HOUR_OF_DAY, 0);
		endCalendar.set(Calendar.MINUTE, 0);
		endCalendar.set(Calendar.SECOND, 0);
		endCalendar.set(Calendar.MILLISECOND, 0);
		long millSecDiff = endCalendar.getTimeInMillis() - startCalendar.getTimeInMillis();
		int dayDiff = Math.round((millSecDiff / (1000 * 60 * 60 * 24)));
		return dayDiff;
	}

	/**
	 * 2个日期之间相隔多少秒
	 * 
	 * @param start
	 * @param end
	 * @return
	 */
	public static int secondsBetweenDays(Date start, Date end) {
		Calendar startCalendar = getCalendar(start);
		Calendar endCalendar = getCalendar(end);
		long millSecDiff = endCalendar.getTimeInMillis() - startCalendar.getTimeInMillis();
		return (int) (millSecDiff / 1000);
	}

	/**
	 * 判断两个日期是否为同一天（只判断日期，不判断时，分，秒）
	 * 
	 * @param date1
	 *            需要判斷的日期
	 * @param date2
	 *            需要判断的日期
	 * @return
	 */
	public static boolean isTheSameDay(Date date1, Date date2) {
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		if (date1 != null && date2 != null) {
			return StringUtils.equals(formatter.format(date1), formatter.format(date2));
		}
		return false;
	}

	/**
	 * 判断当前的时间是否在当天的statSpacingSecond秒内 例如statSpacingSecond为300秒，
	 * 如果现在时间是00:00:21 返回true 如果是00:05:01，返回false
	 * 
	 * @param statSpacingSecond
	 *            统计的间隔，单位秒 ，
	 * @return
	 */
	public static boolean isCompriseTime(int statSpacingSecond) {
		Date now = new Date();
		Calendar cal = Calendar.getInstance();
		cal.setTime(now);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		if (now.getTime() - cal.getTimeInMillis() <= statSpacingSecond * 1000) { // 统计昨天
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 获取日期的数字形式，例如 2015-10-12 10：10：10  ---> 20151012
	 * @return
	 */
	public static int getDateNumber(){

		SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT);
		
		String dateStr = sdf.format(new Date());
		
		String d[] = dateStr.split("-");
		String result = "";
		for(String s : d){
			result = result +s;
		}
		return Integer.valueOf(result);
	}

	/**
	 * 获取指定时间的前后时间（通过加减小时数）
	 * @param date 指定时间
	 * @param hour 小时数
	 * @return Date
	 */
	public static Date getTimeByHour(Date date,int hour){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.HOUR_OF_DAY,hour);
		return calendar.getTime();
	}

	public static Date getLastHour(){
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.HOUR_OF_DAY,-1);
		return calendar.getTime();
	}

	/**
	 * 当前时间的前几分钟
	 * @param minutes
	 * @return
	 */
	public static Date getLastSomeMinutes(Date date,int minutes){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.MINUTE,-minutes);
		return calendar.getTime();
	}

	public static Date getTimeByDayHour(Date date,int days,int hour){
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH,days);
		calendar.add(Calendar.HOUR_OF_DAY,hour);
		return calendar.getTime();
	}

	/***
	 * 转成格林威治时间
	 *
	 * @param localDate    本地时间字符串
	 * @return
	 */
	private static String localToGMT(String localDate) {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Date result_date;
		long result_time = 0;
		if (null == localDate) {
			return localDate;
		} else {
			try {
				//Locale l = Locale.getDefault();
				format.setTimeZone(TimeZone.getDefault());
				result_date = format.parse(localDate);
				result_time = result_date.getTime();
				format.setTimeZone(TimeZone.getTimeZone("GMT00:00"));
				return format.format(result_time);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return localDate;
	}

	public static long diffSeconds(Date datetime) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(datetime);
      	TimeZone timeZone = TimeZone.getTimeZone("GMT00:00");
      	calendar.setTimeZone(timeZone);
      	return calendar.getTimeInMillis() / 1000;
    }

	public static void main(String[] args) {
		SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE_FORMAT);

		System.out.println(DateUtils.getStartDate(new Date(), PeriodTypeEnum.MONTH));
		System.out.println(DateUtils.getEndDate(new Date(), PeriodTypeEnum.MONTH));
		System.out.println(sdf.format(DateUtils.getNextDays(new Date(), -10)));
		System.out.println(sdf.format(DateUtils.getTimeByDayHour(new Date(), -9, -12)));

//		DateUtils.getNextDays(now,-10),DateUtils.getTimeByDayHour(now,-9,-12)

		System.out.println(localToGMT("2016-08-31 14:08:19"));
		System.out.println(diffSeconds(new Date()));


	}

	public static Calendar getCalendar() {
		Calendar calendar = calendarThreadLocal.get();
		if (calendar == null) {
			calendar = Calendar.getInstance();
			calendarThreadLocal.set(calendar);
		}
		return calendar;
	}

	/**
	 * 获取n天后的23:59:59时间
	 * */
	public static Date getNextDaysEnd(Long timestamp , int days) {
		Calendar calendar = getCalendar();
		calendar.setTime(new Date(timestamp));
		calendar.add(Calendar.DATE, days);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		return calendar.getTime();
	}

}
